package com.edu.service.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.edu.exception.FileException;
import com.edu.repository.FileRespository;
import com.edu.service.FileService;
import com.edu.util.FileHelper;
import com.edu.util.IOHelper;
import com.edu.util.ZFilenameUtils;
import com.edu.vo.FileVO;
import com.edu.vo.SimpleTree;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Service 层 实现
 * 
 * @author Administrator
 *
 */
@Service
public class FileServiceImpl implements FileService {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Value("#{prop.root}")
	private String root;

	@Autowired
	private FileRespository fileRespository;

	/**
	 * 
	 * 创建文件 (支持创建多级目录) 1. 文件名不能含有特殊字符 2. 文件名不能与当前的文件或文件夹重名 3. 文件名必须带有后缀
	 * 如果不符合要求，抛出FileException
	 * 
	 * @param dir
	 * @param name
	 * @throws IOException
	 * @throws FileException
	 */
	@Override
	public void createDocument(String name) throws IOException, FileException {
		// 文件名不能为空的校验应写在controller层
		// 验证文件名合法性
		if (!ZFilenameUtils.isValidDocName(name)) {
			throw new FileException(FileException.NAME_ILLEGAL);
		}
		// 判断是否重名
		//String parent = ZFilenameUtils.concat(root, dir);
		String fullName = ZFilenameUtils.concat(root, name);
		logger.debug(name);
		if (ZFilenameUtils.isRepeatName(fullName)) {
			throw new FileException(FileException.FILE_ALREADY_EXISTS);
		}
		File file = new File(fullName);
		fileRespository.createDocument(file);
	}

	/**
	 * 创建目录 (支持创建多级目录) 1. 文件名不能含有特殊字符 2. 文件名不能与当前的文件或文件夹重名 如果不符合要求，抛出FileException
	 *
	 * @param dir
	 * @param name
	 * @throws IOException
	 * @throws FileException
	 */
	@Override
	public void createDirectory(String name) throws IOException, FileException {
		if (!ZFilenameUtils.isValidDirName(name)) {
			throw new FileException(FileException.NAME_ILLEGAL);
		}
		// 判断是否重名
		//String parent = ZFilenameUtils.concat(root, dir);
		String fullDir = ZFilenameUtils.concat(root, name);
		if (ZFilenameUtils.isRepeatName(fullDir)) {
			throw new FileException(FileException.FILE_ALREADY_EXISTS);
		}
		// 创建目录
		
		File file = new File(fullDir);
		fileRespository.createDir(file);
	}

	@Override
	public void deleteFile(String name) throws FileException, IOException {
		String fullDir = ZFilenameUtils.concat(root, name);
		File file = new File(fullDir);
		fileRespository.deleteFile(file);
	}

	@Override
	public void renameFile(String name, String rename) throws IOException, FileException {
		logger.debug(rename);
		String sourceName = ZFilenameUtils.concat(root, name);
		String targetName = ZFilenameUtils.concat(root, rename);
		if (ZFilenameUtils.isRepeatName(targetName)) {
			throw new FileException(FileException.FILE_ALREADY_EXISTS);
		}
		//FileHelper.reName(rename, new File(fullName));
		File source = new File(sourceName);
		File target = new File(targetName);
		fileRespository.renameFile(source, target);
	}


	@Override
	public void downloadFile(String name) {
		// TODO Auto-generated method stub

	}

	@Override
	public List<FileVO> enterDirectory(String dir) throws FileException {
		List<FileVO> list = new ArrayList<>();

		logger.debug("{}", dir == null);
		logger.debug(root);
		String dirName = ZFilenameUtils.concat(root, dir);
		logger.debug(dirName);
		File file = new File(dirName);
		// 判断是文件还是目录
		if (file.exists() && file.isDirectory()) {
			list = fileRespository.getDirContent(file);
		} else {
			logger.debug("文件不存在或不是目录！！");
			throw new FileException(FileException.FILE_NOT_DIRECTORY);
		}
		return list;
	}

	@Override
	public void uploadFile(MultipartFile file) throws FileNotFoundException {

		String fileName = file.getOriginalFilename();
		String fullName = ZFilenameUtils.concat(root, fileName);

		FileOutputStream fos = new FileOutputStream(fullName);
		try {
			fos.write(file.getBytes());
			fos.flush();
			fos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public String showDocument(String name) throws FileNotFoundException, IOException {
		logger.debug(name);
		String fullName = ZFilenameUtils.concat(root, name);

		StringBuilder result = new StringBuilder();
		try {
			BufferedReader br = new BufferedReader(new FileReader(fullName));// 构造一个BufferedReader类来读取文件
			String s = null;
			while ((s = br.readLine()) != null) {// 使用readLine方法，一次读一行
				result.append(System.lineSeparator() + s);
			}
			br.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result.toString();
	}

	@Override
	public void editDocument(String name, String text) throws FileException {
		logger.debug("editDocument:{}", text);
		String fullName = ZFilenameUtils.concat(root, name);
		// FileUtils.
		IOHelper.writeTxtFile(text, new File(fullName));
	}

	@Override
	public SimpleTree getFileTree() throws FileException {
		SimpleTree tree = new SimpleTree("root");
		fileRespository.iteratorPath(root, tree);
		return tree;
	}

	@Override
	public void copyToDir(String name, String targetDir) throws IOException {
		String sourceName = ZFilenameUtils.concat(root, name);
		String targetName = ZFilenameUtils.concat(root, targetDir);
		
		File source = new File(sourceName);
		File target = new File(targetName);
//		if (!target.exists()) {
//			fileRespository.createDir(target);
//		}
		fileRespository.copyToDir(source, target);
		
		
	}

	@Override
	public File getFileByName(String name) {
		String fileName = ZFilenameUtils.concat(root, name);	
		return new File(fileName);
	}
	
}
